package com.sky.common.task;

import com.sky.business.sys.domain.Container;
import com.sky.business.sys.domain.Node;
import com.sky.business.sys.domain.SystemConfig;
import com.sky.business.sys.service.ContainerService;
import com.sky.business.sys.service.NodeService;
import com.sky.business.sys.service.SystemConfigService;
import com.sky.common.docker.ContainerClient;
import com.sky.common.docker.ContainerOperateService;
import com.sky.common.docker.container.ContainerInfo;
import com.sky.common.config.CacheConstants;
import com.sky.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 节点容器状态同步任务
 *
 */
@Slf4j
@Component
public class ContainerStatusSyncTask {

    @Autowired
    private NodeService nodeService;

    @Autowired
    private ContainerService containerService;

    @Autowired
    private ContainerOperateService containerOperateService;

    @Autowired
    private SystemConfigService systemConfigService;




    /**
     * 同步节点的状态信息
     *
     * @param systemConfig 系统配置
     * @param node 节点
     */
    public void syncContainer(SystemConfig systemConfig,Node node) {
        ContainerClient containerClient;
        if(StringUtils.isEmpty(systemConfig.getCertificatePath())) {
            containerClient = new ContainerClient(node.getIpAddr(), node.getContainerPort());
        }else{
            containerClient = new ContainerClient(node.getIpAddr(),node.getContainerPort(),systemConfig.getCertificatePath());
        }
        List<ContainerInfo> containerInfoList = containerOperateService.listAll(containerClient);
        Map<String, ContainerInfo> containerInfoMap = containerInfoList.stream().collect(Collectors.toMap(r -> r.getDockerId(), r -> r));
        List<Container> containerList = containerService.findByNode(node.getId());
        Set<String> containerIdSet = new HashSet<>();
        for (Container container : containerList) {
            String dockerId = container.getDockerId();
            containerIdSet.add(dockerId);
            ContainerInfo containerInfo = containerInfoMap.get(dockerId);
            if (containerInfo != null) {
                //保存最新状态
                container.setStatus(containerInfo.getStatus());
            }else{
                //删除容器记录
                container.setIsDel(true);
            }
            containerService.updateById(container);
        }
        //扫描非法容器
        for (ContainerInfo containerInfo : containerInfoList) {
            String containerName = containerInfo.getName();
            if (containerName.contains(CacheConstants.TRACK_CONTAINER_NAME_PREFIX)
                    || containerName.contains(CacheConstants.STREAM_CONTAINER_NAME_PREFIX)
                    || containerName.contains(CacheConstants.MONITOR_CONTAINER_NAME)) {
                if (!containerIdSet.contains(containerInfo.getDockerId())) {
                    //停止非法容器
                    try {
                        log.info("开始删除未记录容器,节点ID:{},节点IP:{},容器ID:{},容器名称:{}",node.getId(), node.getIpAddr(), containerInfo.getDockerId(), containerName);
                        containerOperateService.remove(containerClient, containerInfo.getDockerId(), true);
                    } catch (Exception e) {
                        log.error("删除未记录容器发生异常,节点ID:{},节点IP:{},容器ID:{},容器名称:{}", node.getId(), node.getIpAddr(), containerInfo.getDockerId(), containerName, e);
                    }
                }
            }
        }
    }


    @Scheduled(cron = "0 */2 * * * ?")
    public void doTask() {
        SystemConfig systemConfig = systemConfigService.getSystemConfig();
        List<Node> nodeList = nodeService.listUndelete();
        for (Node node : nodeList) {
            try {
                syncContainer(systemConfig,node);
            } catch (Exception e) {
                log.error("同步容器状态发生异常,节点ID:{}", node.getId(), e);
            }
        }
    }
}
